package com.zmn.oms.zmn.business.impl.acceptance;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.zmn.anole.dubbo.interfaces.AnoleRemoteService;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.base.common.data.common.query.tags.TagsQuery;
import com.zmn.base.common.data.dubbo.interfaces.tags.TagsListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageGetSendInfoService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.business.interfaces.messageV1.wechat.MessageWeChatTemplateService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.business.interfaces.work.OrderWorkPositionBService;
import com.zmn.oms.common.annotation.OrderWorkChangeSync;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.enums.OrderAcceptanceEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.DateTimeUtil;
import com.zmn.oms.model.dto.acceptance.OrderWorkAcceptanceDTO;
import com.zmn.oms.model.dto.acceptance.ResultOrderAcceptanceDTO;
import com.zmn.oms.model.dto.finalprice.RefundDifferenceDTO;
import com.zmn.oms.model.dto.messageV1.AppMessageDTO;
import com.zmn.oms.model.dto.work.masterwork.CompleteDTO;
import com.zmn.oms.model.dto.work.position.OrderWorkPositionManualSyncDIO;
import com.zmn.oms.model.entity.acceptance.OrderWorkAcceptance;
import com.zmn.oms.model.entity.acceptance.OrderWorkAcceptanceDbQuery;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.orderappbind.OrderThirdAppBind;
import com.zmn.oms.model.entity.visit.OrderVisit;
import com.zmn.oms.model.entity.visit.OrderVisitQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.services.interfaces.acceptance.OrderWorkAcceptanceService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.visit.OrderVisitService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.acceptance.OrderWorkAcceptanceBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.oms.zmn.normal.business.interfaces.refund.RefundBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.masterwork.ZsNormalMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.saas.dubbo.dto.shop.MiniProgramQRCodeDIO;
import com.zmn.saas.dubbo.interfaces.wechat.WeChatMiniProgramRemoteService;
import com.zmn.uuc.dubbo.interfaces.user.UserThirdListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：验收业务接口
 *
 * @author wangxiaokun
 * @since 2021/09/18 14:24
 */
@Slf4j
@Service
public class OrderWorkAcceptanceBServiceImpl implements OrderWorkAcceptanceBService {

    // 定金接口
    private static final String ACCEPTANCE_DEPOSIT_URL = "/subPackages/order/acceptance/deposit";
    // 服务完成接口
    private static final String ACCEPTANCE_PAYMENT_URL = "/subPackages/order/acceptance/acceptance";

    @Autowired
    private OrderWorkAcceptanceService orderWorkAcceptanceService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private MessageSendBaseService messageSendBaseService;
    @Autowired
    private MessageWeChatTemplateService messageWeChatTemplateService;
    @Autowired
    private MessageGetSendInfoService messageGetSendInfoService;
    @Autowired
    private OrderVisitService orderVisitService;
    @Autowired
    private ZsNormalMasterWorkBService zsNormalMasterWorkBService;
    @Autowired
    private WorkFlowContextBService workFlowContextBService;
    @Autowired
    private OrderWorkListBService orderWorkListBService;
    @Autowired
    private OrderExtendService orderExtendService;
    @Autowired
    private OrderWorkPositionBService orderWorkPositionBService;
    @Resource
    private RedisManager redisManager;
    @Autowired
    private RefundBService refundBService;

    @Autowired
    private OrderLogBService orderLogBService;

    @Reference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private WeChatMiniProgramRemoteService weChatMiniProgramRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private TagsListRemoteService tagsListRemoteService;
    @Reference(version = AnoleRemoteService.VERSION, check = false)
    private AnoleRemoteService anoleRemoteService;
    @DubboReference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION,check = false)
    private UserThirdListRemoteService userThirdListRemoteService;
    private final String NO_ATTENTION_WECHAT = "发送失败，用户未关注公众号";

    /**
     * 根据验收id查询单个验收详情
     *
     * @param acceptanceId
     * @return
     */
    @Override
    public OrderWorkAcceptance getOrderWorkAcceptanceByAcceptanceIdAndOrderId(Long acceptanceId, Long orderId) {
        return orderWorkAcceptanceService.findOrderWorkAcceptanceByKey(acceptanceId, orderId);
    }

    /**
     * 根据查询条件查询多个订单验收
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderWorkAcceptance> listOrderWorkAcceptanceByQuery(OrderWorkAcceptanceDbQuery query) {
        return null;
    }

    /**
     * 新增订单验收
     *
     * @param dto
     */
    @Override
    @OrderWorkChangeSync
    public ResultOrderAcceptanceDTO addOrderWorkAcceptance(OrderWorkAcceptanceDTO dto) throws OmsBaseException {

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(dto.getOrderId(), dto.getWorkId());

        ResultOrderAcceptanceDTO resultDTO = new ResultOrderAcceptanceDTO();

        // 如果验收id不为空
        if (NumberUtil.isNotNullOrZero(dto.getAcceptanceId())) {
            OrderWorkAcceptance acceptance = orderWorkAcceptanceService.findOrderWorkAcceptanceByKeySrcMaster(dto.getAcceptanceId(), dto.getOrderId());
            if (!Objects.equals(acceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL)
                    && !Objects.equals(acceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL)) {
                resultDTO.setAcceptanceId(acceptance.getAcceptanceId());
                resultDTO.setAcceptanceResultStatus(acceptance.getAcceptanceResultStatus());
                // 更新上门表
                this.updateOrderVisit(dto);
                if (Objects.equals(acceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT)) {
                    // 判断用户是否关注微信公众号
                    this.judgeWeChat(orderWork, dto, resultDTO);
                }
                return resultDTO;
            }
        } else {
            // 查询验收状态不是失败的
            OrderWorkAcceptanceDbQuery query = new OrderWorkAcceptanceDbQuery();
            query.setOrderId(dto.getOrderId());
            query.setWorkId(dto.getWorkId());
            query.setNonAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL);
            query.setAcceptanceType(dto.getAcceptanceType());
            List<OrderWorkAcceptance> list = orderWorkAcceptanceService.listOrderWorkAcceptanceByQuerySrcMaster(query);
            if (CollectionUtil.isNotNullOrEmpty(list)) {
                OrderWorkAcceptance acceptance = list.get(0);
                // 如果是待验收返回临时二维码地址
                if (Objects.equals(acceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT)) {
                    dto.setAcceptanceId(acceptance.getAcceptanceId());
                    resultDTO.setAcceptanceId(acceptance.getAcceptanceId());
                    resultDTO.setAcceptanceResultStatus(acceptance.getAcceptanceResultStatus());
                    // 更新上门表
                    this.updateOrderVisit(dto);
                    // 判断用户是否关注微信公众号
                    this.judgeWeChat(orderWork, dto, resultDTO);
                    return resultDTO;
                } else if (Objects.equals(acceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)){
                    if (Objects.equals(acceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT)) {
                        resultDTO.setAcceptanceId(acceptance.getAcceptanceId());
                        resultDTO.setAcceptanceResultStatus(acceptance.getAcceptanceResultStatus());
                        return resultDTO;
                    }
                }
            }
        }

        // 真正插入订单验收
        dto.setAcceptanceId(null);
        dto.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT);
        if (Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            orderWorkAcceptanceService.insertOrderWorkDepositAcceptance(dto);
        } else {
            orderWorkAcceptanceService.insertOrderWorkAcceptance(dto);
        }
        resultDTO.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT);
        resultDTO.setAcceptanceId(dto.getAcceptanceId());

        // 更新上门表
        this.updateOrderVisit(dto);
        // 判断用户是否关注微信公众号
        this.judgeWeChat(orderWork, dto, resultDTO);

        // 尾款验收，记录位置信息
        if (Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT) ||
                Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT_CONFIRM)) {
            try {
                OrderWorkPositionManualSyncDIO dio = new OrderWorkPositionManualSyncDIO();
                dio.setLatitude(dto.getLatitude());
                dio.setLongitude(dto.getLongitude());
                orderWorkPositionBService.manualSyncMasterPayLocation(orderWork, dio);
            } catch (Exception ex){
            }
        }

        return resultDTO;
    }

    /**
     * 更新到上门表
     *
     * @param dto
     */
    private void updateOrderVisit(OrderWorkAcceptanceDTO dto) {
        // 更新上门表验收信息
        if (NumberUtil.isNotNullOrZero(dto.getVisitId())) {
            OrderVisit orderVisit = new OrderVisit();
            orderVisit.setVisitId(dto.getVisitId());
            orderVisit.setOrderId(dto.getOrderId());
            orderVisit.setAcceptanceId(dto.getAcceptanceId());
            orderVisit.setAcceptanceResultStatus(dto.getAcceptanceResultStatus());
            orderVisit.setUpdater(dto.getOperator());
            orderVisitService.updateByKey(orderVisit);
        }
    }

    /**
     * 判断是否关注微信公众号，未关注展示小程序临时二维码，已关注发送微信消息
     *
     * @param orderWork
     * @param orderWorkAcceptanceDTO
     * @param resultDTO
     */
    private void judgeWeChat(OrderWork orderWork, OrderWorkAcceptanceDTO orderWorkAcceptanceDTO, ResultOrderAcceptanceDTO resultDTO) throws OmsBaseException {

        // 确认类验收不发送微信公众号信息
        if (Objects.equals(orderWorkAcceptanceDTO.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT_CONFIRM)
                || Objects.equals(orderWorkAcceptanceDTO.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PROGRESS_CONFIRM)) {
            return;
        }

        boolean isSend = false;
        if (NumberUtil.isNullOrZero(orderWork.getVisitUserId())) {
            OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
            if (Objects.isNull(orderExtend) || NumberUtil.isNullOrZero(orderExtend.getWeChatScanUserId())) {
                resultDTO.setIsSendWeChatMessage(isSend);
                // 设置临时小程序临时二维码
                resultDTO.setTemporaryQrCodeUrl(this.getTemporaryWeChatQrCodeUrl(orderWorkAcceptanceDTO, orderWork));
                return;
            }
            orderWork.setVisitUserId(orderExtend.getWeChatScanUserId());
        }

        // 检验用户是否关注
        Boolean attentionWechat = isAttentionWeChat(orderWork);
        if (!attentionWechat){
            resultDTO.setIsSendWeChatMessage(isSend);
            // 设置临时小程序临时二维码
            resultDTO.setTemporaryQrCodeUrl(this.getTemporaryWeChatQrCodeUrl(orderWorkAcceptanceDTO, orderWork));
            return;
        }

        // 发送微信模板消息
        OrderWorkAcceptance orderWorkAcceptance = BeanMapper.map(orderWorkAcceptanceDTO, OrderWorkAcceptance.class);
        isSend = this.sendAcceptanceWeCharMessage(orderWork, orderWorkAcceptance);
        resultDTO.setIsSendWeChatMessage(isSend);

        // 设置临时小程序临时二维码
        resultDTO.setTemporaryQrCodeUrl(this.getTemporaryWeChatQrCodeUrl(orderWorkAcceptanceDTO, orderWork));
    }

    /**
     * 重新发送验收微信消息
     *
     * @param orderId
     */
    @Override
    public void sendWeChatMessage(Long orderId, Long acceptanceId) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        OrderWorkAcceptance orderWorkAcceptance = orderWorkAcceptanceService.findOrderWorkAcceptanceByKey(acceptanceId, orderId);
        // 不是待验收不发送消息
        if (!Objects.equals(orderWorkAcceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT)) {
            return;
        }
        if (NumberUtil.isNullOrZero(orderWork.getVisitUserId())) {
            OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderWork.getOrderId());
            if (Objects.isNull(orderExtend) || NumberUtil.isNullOrZero(orderExtend.getWeChatScanUserId())) {
                throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE,NO_ATTENTION_WECHAT);
            }
            orderWork.setVisitUserId(orderExtend.getWeChatScanUserId());
        }
        // 检验用户是否关注
        checkAttentionWeChat(orderWork);

        this.sendAcceptanceWeCharMessage(orderWork, orderWorkAcceptance);
    }

    /**
     * 验收发送微信模板消息
     *
     * @param orderWork
     * @return
     */
    private Boolean sendAcceptanceWeCharMessage(OrderWork orderWork, OrderWorkAcceptance orderWorkAcceptance) {
        if (Objects.equals(orderWorkAcceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            return messageWeChatTemplateService.sendDesignatedOpenIdWeChatTemplate(orderWork.getOrderId(), MessageConsts.ZMN_WECHAT_MSG_RULEID_ORDER_ACCEPTANCE_DEPOSIT, orderWork.getVisitUserId(), null, orderWorkAcceptance.getAcceptanceId());
        } else {
            if (Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
                return messageWeChatTemplateService.sendDesignatedOpenIdWeChatTemplate(orderWork.getOrderId(), MessageConsts.ZMN_WECHAT_MSG_RULE_ID_QUOTATION_THREE_PAYMENT, orderWork.getVisitUserId(), null, orderWorkAcceptance.getAcceptanceId());
            } else {
                return messageWeChatTemplateService.sendDesignatedOpenIdWeChatTemplate(orderWork.getOrderId(), MessageConsts.ZMN_WECHAT_MSG_RULEID_ORDER_ACCEPTANCE_PAYMENT, orderWork.getVisitUserId(), null, orderWorkAcceptance.getAcceptanceId());
            }
        }
    }

    /**
     * 设置临时小程序临时二维码
     *
     * @param dto
     * @param orderWork
     */
    private String getTemporaryWeChatQrCodeUrl(OrderWorkAcceptanceDTO dto, OrderWork orderWork) {

        OrderThirdAppBind orderThirdAppBind = messageGetSendInfoService.getOrderWeChatBindInfoForOrderBy(orderWork.getOrderId(), orderWork.getPlatWork());
        if (Objects.isNull(orderThirdAppBind)) {
            log.info("服务验收获取二维码失败，订单{}未绑定公众号 ===========", orderWork.getOrderId());
            return null;
        }

        // 渠道写死，40001是微信小程序
        MiniProgramQRCodeDIO dio = new MiniProgramQRCodeDIO();
        dio.setChannelId(40001);
        dio.setThirdAppId(orderThirdAppBind.getThirdAppId());
        if (Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            dio.setPath(ACCEPTANCE_DEPOSIT_URL);
        } else {
            dio.setPath(ACCEPTANCE_PAYMENT_URL);
        }
        dio.setPathParams("orderId=" + orderWork.getOrderId() + "&acceptanceId=" + dto.getAcceptanceId());
        log.info("[{}]获取微信临时小程序临时二维码入参：【{}】", orderWork.getOrderId(), JSON.toJSONString(dio));
        ResponseDTO<String> responseDTO = weChatMiniProgramRemoteService.createMiniProgramTemporaryQRCode(dio);
        log.info("[{}]获取微信临时小程序临时二维码出参：【{}】", orderWork.getOrderId(), JSON.toJSONString(responseDTO));
        if (responseDTO.isSuccess() && Objects.nonNull(responseDTO.getData())) {
            return responseDTO.getData();
        }
        return null;
    }

    /**
     * 修改订单验收
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyOrderWorkAcceptance(OrderWorkAcceptanceDTO dto) throws OmsBaseException {

        log.info("#modifyOrderWorkAcceptance# 入参：[{}]", JSON.toJSONString(dto));
        OrderWorkAcceptance orderWorkAcceptance = BeanMapper.map(dto, OrderWorkAcceptance.class);

        OrderWorkAcceptance dbOrderWorkAcceptance = orderWorkAcceptanceService.findOrderWorkAcceptanceByKeySrcMaster(dto.getAcceptanceId(), dto.getOrderId());
        if (Objects.isNull(dbOrderWorkAcceptance)) {
            log.error("[{}]验收不存在，验收id：{}", dto.getOrderId(), dto.getAcceptanceId());
            return;
        }
        dto.setDbOrderWorkAcceptance(dbOrderWorkAcceptance);

        // h5确认记录手机号
        this.processH5Confirm(dto);

        // 如果验收失败返回失败
        if (Objects.equals(dbOrderWorkAcceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL)) {
            throw new OmsBaseException("本次验收未通过");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(dbOrderWorkAcceptance.getOrderId(), dbOrderWorkAcceptance.getWorkId());
        dto.setOrderId(orderWork.getOrderId());
        dto.setWorkId(orderWork.getWorkId());

        // 验证失败存储失败缘由
        if (Objects.equals(orderWorkAcceptance.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL)) {

            // 如果是失败类型是验机报告失败，默认塞失败原因
            if (NumberUtil.isNotNullOrZero(orderWorkAcceptance.getFailType())
                    && !Objects.equals(orderWorkAcceptance.getFailType(), OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_DEFAULT)) {
                Map<Integer, String> reasonMap = new HashMap<>(1);
                switch (orderWorkAcceptance.getFailType()) {
                    case OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_INSPECTION_REPORT:
                        reasonMap.put(1, "要求工程师重新验机");
                        break;
                    case OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_COST_DETAIL:
                        reasonMap.put(2, "收费异常，对收费有疑问");
                        break;
                    case OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_SERVICE_CONTENT:
                        reasonMap.put(3, "要求工程师完成服务项目");
                        break;
                    default:
                        break;
                }
                dto.setReasonMap(reasonMap);
            }
            if (Objects.nonNull(dto.getReasonMap())) {
                StringJoiner ids = new StringJoiner(",");
                StringJoiner values = new StringJoiner(",");
                dto.getReasonMap().forEach((key, value) -> {
                    ids.add(String.valueOf(key));
                    values.add(value);
                });
                orderWorkAcceptance.setReasonIds(ids.toString());
                orderWorkAcceptance.setReasonValues(values.toString());
            }
            if (NumberUtil.isNullOrZero(dto.getFailType())) {
                orderWorkAcceptance.setFailType(OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_DEFAULT);
            }
        }

        orderWorkAcceptance.setAcceptanceId(dto.getAcceptanceId());
        orderWorkAcceptance.setAcceptanceResultStatus(dto.getAcceptanceResultStatus());
        orderWorkAcceptance.setUpdater(dto.getOperator());
        orderWorkAcceptance.setUpdateTime(dto.getOperateTime());
        dto.setOrderWorkAcceptance(orderWorkAcceptance);

        if (Objects.equals(dbOrderWorkAcceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            switch (dto.getAcceptanceResultStatus()) {
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS:
                    // 定金确认
                    orderWorkAcceptanceService.depositConfirmAcceptance(dto);
                    break;
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL:
                    // 验收失败
                    orderWorkAcceptanceService.updateOrderWorkAcceptanceByKey(dto);
                    break;
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_NON:
                    // 工程师代确认
                    orderWorkAcceptanceService.engineerConfirmAcceptance(dto);
                    break;
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL:
                    // 取消定金确认
                    orderWorkAcceptanceService.cancelDepositAcceptance(dto);
                    break;
                default:
                    break;
            }
        } else {
            switch (dto.getAcceptanceResultStatus()) {
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS:
                    // 验收
                    orderWorkAcceptanceService.updateOrderWorkAcceptanceByKey(dto);
                    break;
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL:
                    // 验收失败
                    orderWorkAcceptanceService.updateOrderWorkAcceptanceByKey(dto);
                    break;
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_NON:
                    // 无需验收
                    orderWorkAcceptanceService.engineerAcceptance(dto);
                    break;
                case OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL:
                    // 取消验收
                    orderWorkAcceptanceService.cancelAcceptance(dto);
                    break;
                default:
                    break;
            }
        }

        // 如果上门不是空更新验收结果
        if (NumberUtil.isNotNullOrZero(dbOrderWorkAcceptance.getVisitId())) {
            OrderVisit orderVisit = new OrderVisit();
            orderVisit.setVisitId(dbOrderWorkAcceptance.getVisitId());
            orderVisit.setOrderId(dbOrderWorkAcceptance.getOrderId());
            orderVisit.setAcceptanceResultStatus(dto.getAcceptanceResultStatus());
            orderVisit.setUpdater(dto.getOperator());

            OrderVisitQuery query = new OrderVisitQuery();
            query.setOrderId(dto.getOrderId());
            query.setVisitId(dbOrderWorkAcceptance.getVisitId());
            OrderVisit dbOrderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
            if (NumberUtil.isNullOrZero(dbOrderVisit.getOrderPayId())) {
                if (Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)
                        || Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON)) {
                    orderVisit.setPayStatus(PayConsts.PAY_STATUS_DONE);
                }
            }

            orderVisitService.updateByKey(orderVisit);
        }

        // 处理无需验收发送剩余预警app消息
        this.processNonAcceptanceWarn(dto, orderWork);

        // 向app发送验收结果
        this.sendAcceptanceResult(dto, orderWork);

        // 尾款验收，尾款是0，服务完成验收后，完成工单
        this.completeOrder(dto, orderWork);
        this.orderWorkAcceptanceSaveOrderLog(dto,orderWork);
        // 一口价订单退差额
        // copy操作人信息
        if (NumberUtil.isNotNullOrZero(dto.getRefundDifferenceAmount())) {
            RefundDifferenceDTO refundDifferenceDTO = BeanMapper.map(dto, RefundDifferenceDTO.class);
            refundDifferenceDTO.setRefundDifferenceAmount(dto.getRefundDifferenceAmount());
            refundBService.refundDifference(refundDifferenceDTO);
        }

    }

    private void orderWorkAcceptanceSaveOrderLog(OrderWorkAcceptanceDTO dto,OrderWork orderWork) {
        if (Objects.isNull(dto) || Objects.isNull(orderWork)) {
            return;
        }
        if (Objects.isNull(dto.getOperatorId()) || Objects.isNull(dto.getOperatorType())) {
            return;
        }
        int orderLogTypeAcceptEvaluate = OrderLogConsts.ORDER_LOG_TYPE_ACCEPT_EVALUATE;
        OrderLog orderLog = new OrderLog();
        orderLog.setWorkId(orderWork.getWorkId());
        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setType(orderLogTypeAcceptEvaluate);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(orderLogTypeAcceptEvaluate));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setCreateTime(new Date());
        orderLog.setOperatorId(Optional.ofNullable(dto.getOperatorId()).orElse((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
        orderLog.setOperator(Optional.ofNullable(dto.getOperator()).orElse("系统"));
        orderLog.setOperatorType(Optional.ofNullable(dto.getOperatorType()).orElse(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
        StringBuilder content = new StringBuilder();
        content.append("清洁服务评价:\n");
        content.append("用户评价：");
        content.append(Objects.isNull(OrderAcceptanceEnum.getText(dto.getAcceptEvaluate())) ? "-" : OrderAcceptanceEnum.getText(dto.getAcceptEvaluate()));
        orderLog.setContent(content.toString());
        orderLogBService.save(orderLog);
        log.info("#modifyOrderWorkAcceptance# 保存日志成功！");
    }

    /**
     * 处理短信h5验证
     *
     * @param dto
     */
    private void processH5Confirm(OrderWorkAcceptanceDTO dto) throws OmsBaseException {
        // 不是h5确认跳过
        if (!Objects.equals(dto.getAcceptanceResultType(), OrderConsts.ORDER_ACCEPTANCE_RESULT_TYPE_H5)) {
            return;
        }

        // 不是验收成功不执行
        if (!Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)) {
            return;
        }

        // 手机号为空跳过
        if (StringUtil.isBlank(dto.getAcceptVersion())) {
            return;
        }

        // 对参数进行解码
        /*try {
            dto.setAcceptVersion(URLDecoder.decode(dto.getAcceptVersion(), "utf-8"));
        } catch (Exception e) {
            log.info("[{}]URL转码失败：[{}]", dto.getOrderId(), e.getMessage());
        }*/

        ResponseDTO<String> responseDTO = anoleRemoteService.decrypt(dto.getAcceptVersion());
        if (!responseDTO.isSuccess() || StringUtil.isBlank(responseDTO.getData())) {
            throw new OmsBaseException("请重新访问链接进行确认");
        }
        String realPhone = responseDTO.getData();

        // 相同的订单，只算一次
        String sameOrderKey = String.format(RedisKeyConsts.ORDER_SAME_ORDER_PHONE_LIMIT_KEY, dto.getOrderId(), realPhone);
        Long sameOrderPhoneIncr = redisManager.incr(sameOrderKey);
        if (sameOrderPhoneIncr > 1L) {
            log.info("validateVerificationCode#相同的订单不计数 入参：{}-{}", dto.getOrderId(), realPhone);
            return;
        }

        // 将通过的工程师+手机号作为key，查询是否超出每月2次限制。
        String limitKey = String.format(RedisKeyConsts.ORDER_CONFIRM_PHONE_LIMIT_KEY, realPhone);
        Long incr = redisManager.incr(limitKey);

        log.info("validateVerificationCode#验收成功，相同手机号 次数：{}-{}, 入参：{}", limitKey, incr);
        // 设置过期时间
        if (incr == 1L) {
            String monthLastDay = DateUtil.getMonthLastDay(new Date());
            long dateEndTimestamp = DateUtil.getDateEndTimestamp(monthLastDay);
            // 计算本月最后一天秒数，与当前秒数时间差
            long seconds = (dateEndTimestamp - DateUtil.getNowTimestamp());
            redisManager.expire(limitKey, (int) seconds);
        }
    }

    @Override
    public void clearPaymentAcceptance(OrderWorkAcceptanceDTO dto, OrderWork orderWork) {

        // 改价格发送app push消息
        Map<String, Object> params = Maps.newHashMap();
        params.put("order_id", String.valueOf(orderWork.getOrderId()));
        params.put("work_id", String.valueOf(orderWork.getWorkId()));

        AppMessageDTO appMessageDTO = new AppMessageDTO();
        appMessageDTO.setOrderId(orderWork.getOrderId());
        appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
        appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
        appMessageDTO.setPlat(orderWork.getPlatWork());
        appMessageDTO.setMasterId(orderWork.getMasterId());
        appMessageDTO.setRuleId(MessageConsts.APP_PUSH_MSG_RULE_ID_ENGINEER_AGAIN_CONFIRM);
        appMessageDTO.setParams(JSON.toJSONString(params));
        log.info("[{}]改服务项发送app消息-开始", orderWork.getOrderId());
        Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
        log.info("[{}]改服务项发送app消息结果：【{}】-结束", orderWork.getOrderId(), isSuccess);

        OrderWorkAcceptanceDbQuery query = new OrderWorkAcceptanceDbQuery();
        query.setOrderId(dto.getOrderId());
        query.setWorkId(dto.getWorkId());
        List<OrderWorkAcceptance> list = orderWorkAcceptanceService.listOrderWorkAcceptanceByQuery(query);
        if (CollectionUtil.isNullOrEmpty(list)) {
            return;
        }
        List<OrderWorkAcceptance> filterList = list.stream()
                .filter(e -> Objects.equals(e.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT)
                        || Objects.equals(e.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT_CONFIRM))
                .filter(e -> Objects.equals(e.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT)
                        || Objects.equals(e.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)
                        || Objects.equals(e.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON))
                .collect(Collectors.toList());
        if (CollectionUtil.isNullOrEmpty(filterList)) {
            return;
        }
        filterList.forEach(acceptance -> {
            dto.setAcceptanceId(acceptance.getAcceptanceId());
            dto.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL);

            try {
                this.modifyOrderWorkAcceptance(dto);
            } catch (OmsBaseException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 向app发送验收结果
     *
     * @param dto
     * @param orderWork
     */
    private void sendAcceptanceResult(OrderWorkAcceptanceDTO dto, OrderWork orderWork) {
        // 无需验收和取消验收不需要发送qpp 通知消息
        if (!Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON)
                && !Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL)) {
            // 验收结果发送app push消息
            Map<String, Object> params = Maps.newHashMap();
            params.put("order_id", String.valueOf(orderWork.getOrderId()));
            params.put("work_id", String.valueOf(orderWork.getWorkId()));
            params.put("acceptanceResultStatus", dto.getOrderWorkAcceptance().getAcceptanceResultStatus());
            params.put("acceptanceId", dto.getOrderWorkAcceptance().getAcceptanceId());

            int ruleId = 0;
            if (Objects.equals(dto.getDbOrderWorkAcceptance().getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
                ruleId = MessageConsts.APP_PUSH_MSG_RULE_ID_ACCEPTANCE_DEPOSIT;
            } else {
                ruleId = MessageConsts.APP_PUSH_MSG_RULE_ID_ACCEPTANCE_PAYMENT;
                params.put("result", dto.getAcceptanceResultStatus() == OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL ? "未通过" : "通过");
            }

            AppMessageDTO appMessageDTO = new AppMessageDTO();
            appMessageDTO.setOrderId(orderWork.getOrderId());
            appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
            appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
            appMessageDTO.setPlat(orderWork.getPlatWork());
            appMessageDTO.setMasterId(orderWork.getMasterId());
            appMessageDTO.setRuleId(ruleId);
            appMessageDTO.setParams(JSON.toJSONString(params));
            log.info("[{}]验收结果发送app消息-开始", orderWork.getOrderId());
            Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
            log.info("[{}]验收结果发送app消息结果：【{}】-结束", orderWork.getOrderId(), isSuccess);
        }
    }

    /**
     * 尾款验收，尾款是0，服务完成验收后，完成工单
     *
     * @param dto
     * @param orderWork
     */
    private void completeOrder(OrderWorkAcceptanceDTO dto, OrderWork orderWork) {
        if (Objects.equals(dto.getDbOrderWorkAcceptance().getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT)
                && (Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)
                || Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON))) {
            if (NumberUtil.isNullOrZero(orderWork.getMasterAmount())
                    || Objects.equals(orderWork.getPayStatus(), PayConsts.PAY_STATUS_DONE)) {
                // 更新完成
                CompleteDTO completeDTO = new CompleteDTO();
                completeDTO.setOrderId(orderWork.getOrderId());
                completeDTO.setWorkId(orderWork.getWorkId());
                completeDTO.setOperator("系统");
                completeDTO.setOperatorId(1L);
                completeDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                try {
                    zsNormalMasterWorkBService.completeOrder(completeDTO);
                } catch (Exception e) {
                    log.error("[{}]尾款是0，服务完成验收后，自动完成异常", dto.getOrderId());
                    log.error(e.getMessage(), e);
                }

                workFlowContextBService.asyncAutoFlow(dto.getOrderId(), dto.getWorkId());
            }
        }
    }

    /**
     * 处理无需验收预警通知
     *
     * @param dto
     * @param orderWork
     */
    private void processNonAcceptanceWarn(OrderWorkAcceptanceDTO dto, OrderWork orderWork) throws OmsBaseException {

        // 不是无需验收返回
        if (!Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON)) {
            return;
        }
        // 不是工程师操作返回
        if (!Objects.equals(dto.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)) {
            return;
        }

        Integer oneTypeId;
        Integer ruleId;
        if (Objects.equals(dto.getDbOrderWorkAcceptance().getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            oneTypeId = OrderConsts.BASE_CODE_MAP_ONE_TYPE_DEPOSIT_WARN;
            ruleId = MessageConsts.APP_PUSH_MSG_RULE_ID_DEPOSIT_CONFIRM_WARN;
        } else {
            oneTypeId = OrderConsts.BASE_CODE_MAP_ONE_TYPE_ACCEPTANCE_WARN;
            ruleId = MessageConsts.APP_PUSH_MSG_RULE_ID_ACCEPTANCE_WARN;
        }

        TagsQuery dio = new TagsQuery();
        dio.setOneTypeId(oneTypeId);
        dio.setStatus(GlobalConsts.YES);
        ResponseDTO<List<TagsDRO>> responseDTO = tagsListRemoteService.listByTagsDIO(dio);
        if (!responseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(responseDTO.getData())) {
            return;
        }
        int total = Optional.ofNullable(responseDTO.getData().get(0).getTwoTypeId()).orElse(0);

        OrderWorkQuery query = new OrderWorkQuery();
        query.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_NON);
        if (Objects.equals(dto.getDbOrderWorkAcceptance().getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            query.setAcceptanceType(OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT);
        } else {
            query.setNonAcceptanceType(OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT);
        }
        query.setAcceptanceOperatorId(dto.getOperatorId());
        query.setAcceptanceOperatorType(dto.getOperatorType());
        query.setAcceptanceOperateTime(DateUtil.dateFormatToString(DateTimeUtil.getMonthFirstDay(DateUtil.getNow()), DateUtil.FORMAT_DEFAULT)
                + "," + DateUtil.dateFormatToString(DateTimeUtil.getMonthLastDay(DateUtil.getNow()), DateUtil.FORMAT_DEFAULT));
        Integer count = orderWorkListBService.countOrderWorkByQuery(query);

        if (count > total) {
            throw new OmsBaseException("您本月代验收已经到达上限");
        } else {
            Map<String, Object> params = Maps.newHashMap();
            params.put("order_id", String.valueOf(orderWork.getOrderId()));
            params.put("work_id", String.valueOf(orderWork.getWorkId()));
            params.put("count", count);
            params.put("count_surplus", total - count);

            AppMessageDTO appMessageDTO = new AppMessageDTO();
            appMessageDTO.setOrderId(orderWork.getOrderId());
            appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
            appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
            appMessageDTO.setPlat(orderWork.getPlatWork());
            appMessageDTO.setMasterId(orderWork.getMasterId());
            appMessageDTO.setRuleId(ruleId);
            appMessageDTO.setParams(JSON.toJSONString(params));
            log.info("[{}]代用户验收预警通知-开始", orderWork.getOrderId());
            Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
            log.info("[{}]代用户验收预警通知结果：【{}】-结束", orderWork.getOrderId(), isSuccess);
        }
    }

    /**
     * 检验用户是否关注
     * @param orderWork 工单信息
     */
    private void checkAttentionWeChat(OrderWork orderWork) throws OmsBaseException{
        OrderThirdAppBind orderThirdAppBind = messageGetSendInfoService.getOrderWeChatBindInfoForOrderBy(orderWork.getOrderId(), orderWork.getPlatWork());
        if (Objects.isNull(orderThirdAppBind) || StringUtils.isBlank(orderThirdAppBind.getThirdAppId())) {
            log.info("订单号{}，未找到绑定公众号信息", orderWork.getWorkId());
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, NO_ATTENTION_WECHAT);
        }

        ResponseDTO<Boolean> isAttentionWechat = userThirdListRemoteService.getThirdSubscribeByUserIdAndAppId(orderWork.getVisitUserId(), orderThirdAppBind.getThirdAppId());
        log.info("订单号{},查询用户是否关注公众号,userId:{},appId:{},出参:{}",orderWork.getOrderId(),orderWork.getVisitUserId(),orderThirdAppBind.getThirdAppId(),isAttentionWechat);
        if (isAttentionWechat.isSuccess() && Objects.nonNull(isAttentionWechat.getData())){
            if (!isAttentionWechat.getData()){
                throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, NO_ATTENTION_WECHAT);
            }
        }else {
            log.error("调用getThirdSubscribeByUserIdAndAppId查看用户是否关注公众号接口错误");
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, NO_ATTENTION_WECHAT);
        }
    }


    /**
     * 检验用户是否关注
     * @param orderWork 工单信息
     */
    private Boolean isAttentionWeChat(OrderWork orderWork){
        OrderThirdAppBind orderThirdAppBind = messageGetSendInfoService.getOrderWeChatBindInfoForOrderBy(orderWork.getOrderId(), orderWork.getPlatWork());
        if (Objects.isNull(orderThirdAppBind) || StringUtils.isBlank(orderThirdAppBind.getThirdAppId())) {
            log.info("订单号{}，未找到绑定公众号信息", orderWork.getWorkId());
            return false;
        }

        ResponseDTO<Boolean> isAttentionWechat = userThirdListRemoteService.getThirdSubscribeByUserIdAndAppId(orderWork.getVisitUserId(), orderThirdAppBind.getThirdAppId());
        log.info("订单号{},查询用户是否关注公众号,userId:{},appId:{},出参:{}",orderWork.getOrderId(),orderWork.getVisitUserId(),orderThirdAppBind.getThirdAppId(),isAttentionWechat);
        if (isAttentionWechat.isSuccess() && Objects.nonNull(isAttentionWechat.getData())){
            return isAttentionWechat.getData();
        }else {
            log.error("调用getThirdSubscribeByUserIdAndAppId查看用户是否关注公众号接口错误");
            return false;
        }
    }
}
